import modules.mumu as mumu
import modules.ocr as ocr
import modules.operation as operation
import modules.table_print as table_print
import datetime
import easyocr
import threading
import time
import sys
import json
import mmap
import os
import logging
import socket

screenshot = None
reader = None
roi = None
results = ''
operationConfig = None
combatConfig = None 

class CustomFormatter(logging.Formatter):
    def format(self, record):
        timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        level = record.levelname
        message = record.getMessage()
        formatted_log = f"[{timestamp}] {level} - \"{message}\""
        return formatted_log


class UDPHandler(logging.Handler):
    def __init__(self, host, port):
        super().__init__()
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.host = host
        self.port = port

    def emit(self, record):
        try:
            log_entry = {
                'timestamp': datetime.datetime.now().isoformat(),
                'level': record.levelname,
                'message': record.getMessage(),  # 使用原始消息而不是格式化后的
                'logger': record.name,
                'path': record.pathname,
                'line': record.lineno
            }
            self.sock.sendto(json.dumps(log_entry).encode('utf-8'), (self.host, self.port))
        except Exception as e:
            print(f"Failed to send log over UDP: {e}")


def setup_logger(host='127.0.0.1', port=5145):
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.INFO)

    # 创建 UDP 日志处理器
    udp_handler = UDPHandler(host, port)
    # 使用自定义格式化器
    formatter = CustomFormatter()
    udp_handler.setFormatter(formatter)

    # 添加控制台处理器
    console_handler = logging.StreamHandler()
    console_handler.setFormatter(formatter)

    logger.addHandler(udp_handler)
    logger.addHandler(console_handler)
    return logger

# 读取共享文件
def read_from_mmf():
    kill = False
    try:
        with open('./shared_memory.bin', 'rb') as f:
            mm = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
            data = mm.read()
            decoded_data = data.decode('utf-8').strip()
            if decoded_data.find("kill") >= 0:
                kill = True
            mm.close()
    except Exception as e:
        print(f"Error in Python read: {e}")
    return kill

def real_time_screenshot_ocr():
    """
    实时进行模拟器截屏识别的函数
    """
    global screenshot,reader,roi,results
    while True:
        if read_from_mmf():
            os._exit(1)
        try:
            screenshot = mumu.get_mumu_screenshot_as_cv2()
            results = ocr.ocr_with_easyocr(screenshot,reader,roi,True)
        except Exception as e:
            print(f"截屏出错: {e}")
        time.sleep(0.5)  # 每隔 0.5 秒截屏一次


if __name__ == "__main__":
    time_gap = datetime.timedelta(hours=4)
    weekday = (datetime.datetime.now()-time_gap).weekday()
    logger = setup_logger()

    # with open('config.json', 'r', encoding='utf-8') as f:
    #     config = json.load(f)
    # print(f"操作方案：{config['操作方案']['方案启用']}")
    # col1 = config['操作方案']['操作列表']
    # col2 = []
    # col3 = []
    # col2 = [config['操作方案']['体力预计变化'][name] for name in col1]
    # for item in config['操作方案']['方案列表']:
    #     if item['方案名'] == config['操作方案']['方案启用']:
    #         col3 = [item['方案操作'][name] for name in col1]
    # table_print.p(col1,col2,col3)

    # comfire = input(f"开启代理(y/n)？")
    # if comfire != 'y' and comfire != 'Y' and comfire != 'yes':
    #     sys.exit(0)

    logger.warning("自动代理开始...")
    st = time.time()

    
    # ---------启动游戏----------
    if mumu.launch_app():
        logger.info("恋与深空，启动")
        logger.info("初始化 EasyOCR ...")
        # 初始化 EasyOCR，支持中文和英文，并指定使用 GPU（gpu=True）,减少初始化的时间
        try:
            reader = easyocr.Reader(['ch_sim', 'en'], gpu=True, verbose=True, model_storage_directory='./model_cache')
        except Exception as e:
            print(f"出现错误: {e}")
        # 开启多线程进行实时截屏识别
        screenshot_thread = threading.Thread(target=real_time_screenshot_ocr)
        screenshot_thread.daemon = True  # 设置为守护线程，主线程退出时自动退出
        screenshot_thread.start()
        with open('./resource/config.json', 'r', encoding='utf-8') as f:
            config = json.load(f)
            for item in config['操作方案']['方案列表']:
                if config['操作方案']['方案启用'] == item['方案名']:
                    operationConfig = item
                    break
            combatConfig = config['战斗方案']
    else:
        sys.exit(0)

    # ---------游戏唤醒----------
    if operationConfig['方案操作']['游戏唤醒']:
        logger.info("等待唤醒...")
        while True: 
            if results.find("临空市") >= 0:
                if  results.find("公告") >= 0:
                    mumu.perform_adb_tap(365,1045)
                    time.sleep(0.2)
                    mumu.perform_adb_tap(365,1045)
                    time.sleep(0.2)
                    mumu.perform_adb_tap(365,1045)
                    time.sleep(0.2)
                    break
                else:
                    mumu.perform_adb_tap(365,1045)
                    time.sleep(0.2)
                    mumu.perform_adb_tap(365,1045)
                    break
            time.sleep(0.5)
            continue        
        
        mumu.perform_adb_tap(365,1045)
        logger.info("唤醒成功！")
        time.sleep(0.5)

    # ---------登录、交互----------
    if operationConfig['方案操作']['日常交互']:
        logger.info("登录、交互...")
        while results.find("日程") < 0: 
            time.sleep(0.5) 
            continue
        screenshot = mumu.get_mumu_screenshot_as_cv2()
        roi = None
        temp_results = ocr.ocr_with_easyocr(screenshot,reader,roi,False)
        username = temp_results[1]['text']
        logger.warning(f"欢迎回来，{username}")
        mumu.perform_adb_tap(285,600)
        logger.info("登录、交互完成！\n")
        time.sleep(0.5)

    # ---------每日免费礼包----------
    if operationConfig['方案操作']['每日礼包']:
        logger.info("每日免费礼包领取...")
        while results.find("日程") < 0 or results.find("活动") < 0: 
            time.sleep(0.5) 
            continue
        mumu.perform_adb_tap(665,945)
        while results.find("礼包") < 0: 
            time.sleep(0.5) 
            continue
        time.sleep(0.2)
        mumu.perform_adb_tap(245,215)
        time.sleep(0.5)
        mumu.perform_adb_scroll_to_bottom()
        mumu.perform_adb_scroll_to_bottom()
        mumu.perform_adb_scroll_to_bottom()   
        mumu.perform_adb_scroll_to_bottom()
        while results.find("免费") < 0: 
            time.sleep(0.5) 
            continue 
        temp_screenshot = mumu.get_mumu_screenshot_as_cv2()
        temp_results = ocr.ocr_with_easyocr(temp_screenshot,reader,roi,False)
        print(temp_results)
        index = 0
        for item in temp_results:
            print(item)
            if item['text'] == '免费' and index == 1:
                x,y,w,h = item['bbox']
                time.sleep(0.2)
                mumu.perform_adb_tap(x + (w // 2),y + (h // 2))
                time.sleep(0.2)
                mumu.perform_adb_tap(x + (w // 2),y + (h // 2))
                time.sleep(0.2)
                mumu.perform_adb_tap(28,728)
                time.sleep(0.2)
                mumu.perform_adb_tap(28,728)
                time.sleep(0.2)
                mumu.press_esc() 
                break
            elif item['text'] == '免费' and index < 1:
                print(item)
                index += 1
        while results.find("特权") < 0: 
            time.sleep(0.5) 
            continue
        time.sleep(0.2)
        mumu.press_esc()        

    # ---------零点追踪----------
    if operationConfig['方案操作']['零点追踪']:
        if combatConfig['零点追踪']['模式'] == "自动":
            logger.info("零点追踪开始...")
            while results.find("日程") < 0 or results.find("商城") < 0: 
                time.sleep(0.5) 
                continue
            mumu.perform_adb_tap(675,668)
            while results.find("任务") < 0: 
                time.sleep(0.5) 
                continue
            mumu.perform_adb_tap(143,1215)
            time.sleep(0.2) 
            mumu.perform_adb_tap(143,1215)
            while results.find("零点追踪") < 0: 
                time.sleep(0.5) 
                continue
            temp_screenshot = mumu.get_mumu_screenshot_as_cv2()
            temp_results = ocr.ocr_with_easyocr(temp_screenshot,reader,roi,True)
            ZeroPoint = []
            for boss in combatConfig['零点追踪']['BOSS列表']:
                if temp_results.find(boss) >= 0:
                    ZeroPoint.append(boss)
            logger.info(f"零点追踪目标：{ZeroPoint}")
            mumu.press_esc()
            while results.find("日程") < 0 or results.find("商城") < 0: 
                time.sleep(0.5) 
                continue
            mumu.perform_adb_tap(348,1196)
            while results.find("零点追踪") < 0: 
                time.sleep(0.5) 
                continue
            mumu.perform_adb_tap(270,320)
            while results.find("猎人版") < 0: 
                time.sleep(0.5) 
                continue
            logger.info(f"开始执行零点追踪目标追击")
            for boss in ZeroPoint:
                while results.find(ZeroPoint[0]) < 0 and results.find(ZeroPoint[1]) < 0:
                    time.sleep(0.5) 
                    break
                x = combatConfig['零点追踪']['BOSS坐标'][boss][0]
                y = combatConfig['零点追踪']['BOSS坐标'][boss][1]
                mumu.perform_adb_tap(x,y)
                i = str(combatConfig['零点追踪']['关卡配置'][boss])
                while results.find("9") < 0:
                    time.sleep(0.5) 
                    break
                x = combatConfig['零点追踪']['关卡坐标'][i][0]
                y = combatConfig['零点追踪']['关卡坐标'][i][1]
                mumu.perform_adb_tap(x,y)
                logger.info(f"零点追踪目标：{boss} 关卡：目击点-{i}")
                while results.find("目击点") < 0:
                    time.sleep(0.5) 
                    break
                for count in range(0,int(combatConfig['零点追踪']['追击次数'])):
                    mumu.perform_adb_tap(200,977)
                    logger.info(f"第 {count+1} 次执行 零点追踪目标：{boss} 关卡：目击点-{i} 自动追击x1")
                    while results.find("完成") < 0:
                        time.sleep(0.5) 
                        break
                    time.sleep(0.2) 
                    mumu.perform_adb_tap(200,977)
                while results.find("目击点") < 0:
                    time.sleep(0.5) 
                    break
                time.sleep(0.2)
                mumu.press_esc()
                while results.find("地点") < 0:
                    time.sleep(0.5) 
                    break
                time.sleep(0.2)
                mumu.press_esc()
            logger.info(f"零点追踪完成！\n")
            while results.find("猎人版") < 0:
                time.sleep(0.5) 
                break
            time.sleep(0.2)
            mumu.press_esc()
            while results.find("零点追踪") < 0:
                time.sleep(0.5) 
                break
            time.sleep(0.2)
            mumu.press_esc()
        

    # ---------芯核狩猎----------
    if operationConfig['方案操作']['芯核狩猎']:
        logger.info("芯核狩猎开始...")
        while results.find("日程") < 0 or results.find("商城") < 0: 
            time.sleep(0.5) 
            continue
        mumu.perform_adb_tap(348,1196)
        while results.find("芯核狩猎") < 0: 
            time.sleep(0.5) 
            continue
        mumu.perform_adb_tap(360,720)
        while results.find("芯核一览") < 0: 
            time.sleep(0.5) 
            continue
        if weekday == 6:
            block = combatConfig['芯核狩猎']['默认选择']
            x = combatConfig['芯核狩猎']['区域坐标'][block][0]
            y = combatConfig['芯核狩猎']['区域坐标'][block][1]
            mumu.perform_adb_tap(x,y)
            logger.info(f"芯核狩猎区域：{block}")
        else:
            for i in combatConfig['芯核狩猎']['区域列表']:
                block_open = combatConfig['芯核狩猎']['区域开放时间']
                if weekday == block_open[i][0] or weekday == block_open[i][1]:
                    x = combatConfig['芯核狩猎']['区域坐标'][i][0]
                    y = combatConfig['芯核狩猎']['区域坐标'][i][1]
                    mumu.perform_adb_tap(x,y)
                    logger.info(f"芯核狩猎区域：{i}")
                    break
        while results.find("猎人贴士") < 0: 
            time.sleep(0.5) 
            continue
        if results.find("自动追击") < 0:
            mumu.perform_adb_scroll(360,475,715,475) 
        while results.find("自动追击") < 0: 
            time.sleep(0.5) 
            continue
        mumu.perform_adb_tap(173,1195)
        logger.info("芯核狩猎 自动追击x1")
        while results.find("完成") < 0 and results.find("取消") < 0: 
            time.sleep(0.5) 
            continue
        logger.info("芯核狩猎完成！\n")
        time.sleep(0.2) 
        mumu.press_esc()
        while results.find("猎人贴士") < 0: 
            time.sleep(0.5) 
            continue
        time.sleep(0.2) 
        mumu.press_esc()
        while results.find("芯核一览") < 0: 
            time.sleep(0.5) 
            continue
        time.sleep(0.2) 
        mumu.press_esc()
        while results.find("芯核狩猎") < 0: 
            time.sleep(0.5) 
            continue
        time.sleep(0.2) 
        mumu.press_esc()
        
    # ---------深空试炼----------
    if operationConfig['方案操作']['深空试炼']:
        while results.find("日程") < 0 or results.find("商城") < 0: 
            time.sleep(0.5) 
            continue
        mumu.perform_adb_tap(348,1196)
        while results.find("深空试炼") < 0: 
            time.sleep(0.5) 
            continue
        mumu.perform_adb_tap(263,507)
        logger.info("深空试炼开始....")
        while results.find("期待") < 0: 
            time.sleep(0.5) 
            continue
        block = combatConfig['深空试炼']['默认选择']
        if weekday == 6:
            x = combatConfig['深空试炼']['区域坐标'][block][0]
            y = combatConfig['深空试炼']['区域坐标'][block][1]
            mumu.perform_adb_tap(x,y)
            logger.info(f"深空试炼轨道：{block}")
        else:
            x = combatConfig['深空试炼']['轨道坐标']["开放轨道"][0]
            y = combatConfig['深空试炼']['轨道坐标']["开放轨道"][1]
            isBlock = "开放轨道"
            for i in combatConfig['深空试炼']['轨道列表']:
                block_open = combatConfig['深空试炼']['轨道开放时间']
                if i == block and (weekday == block_open[i][0] or weekday == block_open[i][1]):
                    x = combatConfig['深空试炼']['轨道坐标'][i][0]
                    y = combatConfig['深空试炼']['轨道坐标'][i][1]
                    mumu.perform_adb_tap(x,y)
                    isBlock = i
                    break
            logger.info(f"深空试炼轨道：{isBlock}")
            mumu.perform_adb_tap(x,y)
        while results.find("通关") < 0: 
            print(results)
            time.sleep(0.5) 
            continue
        mumu.perform_adb_tap(552,745)
        while results.find("编队") < 0: 
            time.sleep(0.5) 
            continue
        mumu.perform_adb_tap(482,1176)
        while results.find("动") < 0: 
            mumu.perform_adb_tap(530,660)
            time.sleep(0.2)
            mumu.perform_adb_tap(530,660)
            time.sleep(0.5) 
            continue
        while results.find("退出") < 0: 
            time.sleep(0.5) 
            continue
        logger.info("深空试炼完成！\n")
        mumu.perform_adb_tap(530,660)
        while results.find("轨") < 0: 
            time.sleep(0.5) 
            continue
        time.sleep(0.2)
        mumu.press_esc()
        while results.find("搭档") < 0: 
            time.sleep(0.5) 
            continue
        time.sleep(0.2)
        mumu.press_esc()
        while results.find("深空试炼") < 0: 
            time.sleep(0.5) 
            continue
        time.sleep(0.2)
        mumu.press_esc()

    # ---------体力赠送----------
    if operationConfig['方案操作']['体力赠送']:
        logger.info("体力赠送开始...")
        while results.find("日程") < 0 or results.find("商城") < 0: 
            time.sleep(0.5) 
            continue
        mumu.perform_adb_tap(38,164)
        while results.find("领取") < 0: 
            time.sleep(0.5) 
            continue
        mumu.perform_adb_tap(501,1176)
        logger.info("体力赠送完成！\n")
        time.sleep(0.2) 
        mumu.perform_adb_tap(36,71)

    # ---------一键领取----------
    if operationConfig['方案操作']['一键领取']:
        logger.info("一键领取开始...")
        while results.find("日程") < 0 or results.find("商城") < 0: 
            time.sleep(0.5) 
            continue
        mumu.perform_adb_tap(675,668)
        while results.find("领取") < 0: 
            time.sleep(0.5) 
            continue
        mumu.perform_adb_tap(552,1131)
        time.sleep(0.5)
        mumu.perform_adb_tap(604,289)
        time.sleep(0.2)
        mumu.perform_adb_tap(604,289)
        logger.info("每日活跃奖励一键领取")
        time.sleep(0.5)
        mumu.perform_adb_tap(437,1224)
        time.sleep(1.2)
        if results.find("可领取") > 0: 
            temp_screenshot = mumu.get_mumu_screenshot_as_cv2()
            temp_results = ocr.ocr_with_easyocr(temp_screenshot,reader,roi,False)
            for item in temp_results:
                if item['text'] == '可领取':
                    x,y,w,h = item['bbox']
                    mumu.perform_adb_tap(x + (w // 2),y + (h // 2))
                    logger.info("签到领取")
                    break
            time.sleep(1)
            mumu.press_esc()
        mumu.perform_adb_tap(597,1221)
        while results.find("晚间") < 0:
            time.sleep(0.5) 
            continue
        if results.find("领取") >= 0: 
            temp_screenshot = mumu.get_mumu_screenshot_as_cv2()
            temp_results = ocr.ocr_with_easyocr(temp_screenshot,reader,roi,False)
            for item in temp_results:
                if item['text'] == '领取':
                    x,y,w,h = item['bbox']
                    mumu.perform_adb_tap(x + (w // 2),y + (h // 2))
                    logger.info("领取体力礼包")
                    time.sleep(1)
                    mumu.press_esc()
                    break
        logger.info("一键领取完成！\n")
        time.sleep(0.2)
        mumu.press_esc()

    et = time.time()
    totalTime = format(et-st,'.2f')
    logger.warning(f"自动代理结束！祝您每天开心~\n总共用时{totalTime}s")